
#include "Contract.h"
#include "CardController.h"
#include "Contactless/ISO14443Command.h"
#include "Contactless/ISO14443p3a.h"
#include "Contactless/ISO14443p3b.h"
/************************************************************************/
/* Type A                                                                 */
/************************************************************************/
static int Control_CardA_Detect(WCI* wci) {
	uint8_t dummy[2];
	ISO14443A_SetMode(wci);
	int ret = ISO14443A_RequestA(wci, dummy);
	return ret == WCI_S_OK || ret == WCI_S_Coll;
}

static int Control_CardA_Activate(WCI* wci, uint8_t req, void* info) {
	return ISO14443A_Activate(wci, req, (ISO14443AInfo_T*)info);
}

static int Control_CardA_Deactivate(WCI* wci, void* param) {
	return ISO14443A_Halt(wci, (unsigned int)param);
}

/************************************************************************/
/* Type B                                                                */
/************************************************************************/
#if 1
static int Control_CardB_Detect(WCI* wci) {
	ISO14443BInfo_T info;
	ISO14443B_SetMode(wci);
	int ret = ISO14443B_RequsetB(wci, &info);
	return ret == WCI_S_OK;
}

static int Control_CardB_Activate(WCI* wci, uint8_t req, void* info) {
	return ISO14443B_Activate(wci, PICC_Op_Wakeup, info);
}

static int Control_CardB_Deactivate(WCI* wci, void* param) {
	return ISO14443B_HaltB(wci, (uint8_t*)param);
}
#endif 
/************************************************************************/
/* Mifare                                                               */
/************************************************************************/
#if 1

static int Control_MF_Activate(WCI* wci, uint8_t req, void* info) {
	int ret = ISO14443A_Activate(wci, req, (ISO14443AInfo_T*)info);
	if (ret == CmdS_NotCompliant) {
		return 0;
	}
	return ret;
}
#endif 

/************************************************************************/
/* Collection                                                           */
/************************************************************************/
static const CardController cardControllers[Card_T_CpuMax] = {
	[Card_T_CpuA] = {
		.activate = Control_CardA_Activate,
		.deactivate = Control_CardA_Deactivate,
		.detect = Control_CardA_Detect,
	},
#if 1
	[Card_T_CpuB] = {
		.activate = Control_CardB_Activate,
		.deactivate = Control_CardB_Deactivate,
		.detect = Control_CardB_Detect,
	},
#endif 
};
#if 1

static const CardController memCardControllers[Card_T_MemMax - Card_T_MemBase] = {
	[Card_T_Mifare - Card_T_MemBase] = {
		.activate = Control_MF_Activate,
		.deactivate = Control_CardA_Deactivate,
		.detect = Control_CardA_Detect,
	}
};
#endif 

static const CardController* Controller_Get(uint8_t type) {
	if (type < Card_T_CpuMax) {
		return &cardControllers[type];
	}
	else 
	if(type < Card_T_MemMax){
		return &memCardControllers[type - Card_T_MemBase];
	}
	return (CardController*)0;
}


int Controller_Detect(WCI * wci, uint8_t type)
{
	const CardController* c = Controller_Get(type);
	REQUIRE(c && c->detect);
	return c->detect(wci);
}

int Controller_Activate(WCI * wci, uint8_t type, uint8_t req, void * info)
{
	const CardController* c = Controller_Get(type);
	REQUIRE(c && c->activate);
	return c->activate(wci, req, info);
}

int Controller_Deactivate(WCI * wci, uint8_t type, void * param)
{
	const CardController* c = Controller_Get(type);
	REQUIRE(c && c->deactivate);
	return c->deactivate(wci, param);
}
